#include <gtk/gtk.h>
#include <stdio.h>

#include "gtkutils.h"
#include "gtkutils-extension.h"

#include "fileutils.h"
#include "dirutils.h"
#include "permissionutils.h"

void sayHello() {
    printf("hello word\n");
}

#define CONFIG_DIRECTORY_PATH "/Users/zinface/expect-script/"
#define SSHTO_TEMPLATE \
"#!/usr/bin/expect                               \n"\
"                                                \n"\
"set timeout 30                                  \n"\
"set host \"%s\"                                 \n"\
"set port \"%s\"                                 \n"\
"set username \"%s\"                             \n"\
"set password \"%s\"                             \n"\
"                                                \n"\
"spawn ssh -p$port $username@$host               \n"\
"expect \"*password*\" {send \"$password\\r\"}   \n"\
"interact                                        \n"\

// host, port, username, password

GtkTreeStore *config_list_store;

GtkEntryBuffer *host_entry_buffer;
GtkEntryBuffer *port_entry_buffer;
GtkEntryBuffer *username_entry_buffer;
GtkEntryBuffer *password_entry_buffer;

GtkTextBuffer *config_text_buffer;

void readconfig(char *buffer, char *s) {
    char *trim = LineTrim(buffer);
    GSList *seps = split(trim, ' ');
    char *value;
    if ((value = LineReplace(g_slist_last(seps)->data, "\"", ""))) {
        strcpy(s, value);
        free(value);
    }
    GS_FREE_ALL_CLEAN(seps);
    free(trim);
}

createSignalFunc(click_action_previewconfig) {
    const char *host = entryBufferGetText(host_entry_buffer);
    const char *port = entryBufferGetText(port_entry_buffer);
    const char *username = entryBufferGetText(username_entry_buffer);
    const char *password = entryBufferGetText(password_entry_buffer);

    char buffer[10000] = {0};
    sprintf(buffer, SSHTO_TEMPLATE, host, port, username, password);
    textBufferSetText(config_text_buffer, buffer, strlen(buffer));
}

createSignalObjectFunc(clicked_action_comb_readconfig, GtkComboBox) {
    GtkTreeIter iter;
    if (getComboBoxActiveIter(user_data, &iter)) {
        char *filename = NULL;
        char *path = NULL;
        treeModelGet(convTreeModel(config_list_store), &iter, 0, &filename, 1, &path, -1);
        
        if (path && FileExists(path)) {
            long size = FileLength(path);
            char buffer[size];
            S_CLEARN_SIZE(buffer, size);

            char host[100] = {0};
            char port[100] = {0};
            char username[100] = {0};
            char password[100] = {0};

            if (FileReadToBuffer(path, buffer, size)) {
                GSList *splitT = split(buffer, '\n');
                for (GSList *iter = splitT; iter; iter=iter->next) {
                    // printf("%s-%s-%s-%s\n",host,port,username,password);
                    if (LineStartWith(iter->data, "set host"))      readconfig(iter->data, host);
                    if (LineStartWith(iter->data, "set port"))      readconfig(iter->data, port);
                    if (LineStartWith(iter->data, "set username"))  readconfig(iter->data, username);
                    if (LineStartWith(iter->data, "set password"))  readconfig(iter->data, password);
                }
                GS_FREE_ALL_CLEAN(splitT);


                printf("%s-%s-%s-%s\n",host,port,username,password);
                entryBufferSetText(host_entry_buffer, host);
                entryBufferSetText(port_entry_buffer, port);
                entryBufferSetText(username_entry_buffer, username);
                entryBufferSetText(password_entry_buffer, password);
            }
        }
    }

    click_action_previewconfig(NULL, NULL);
}

createTreeModelFunc(load_configs) {
    GtkTreeIter iter;
    GSList *configs = NULL;
    
    treeStoreClear(config_list_store);

    if(DirFileList(CONFIG_DIRECTORY_PATH, &configs)) {
        for (GSList *config = configs; config; config = config->next) {
            if (!LineStartWith(config->data, "sshto"))
                continue;

            char path[1000] = {0};
            sprintf(path, "%s/%s", CONFIG_DIRECTORY_PATH, convChars(config->data));

            treeStoreAppend(config_list_store, &iter, NULL);
            treeStoreSet(config_list_store, &iter, 0, convChars(config->data), 1, path, -1);
        }
    }
    GS_FREE_ALL_CLEAN(configs);
    return convTreeModel(config_list_store);
}

createSignalObjectFunc(clicked_action_comb_deleteconfig, GtkComboBox) {
    GtkTreeIter iter;
    if (getComboBoxActiveIter(user_data, &iter)) {
        char *filename = NULL;
        char *path = NULL;
        treeModelGet(convTreeModel(config_list_store), &iter, 0, &filename, 1, &path, -1);
        
        if (path && FileExists(path)) {
            unlink(path);
        }
    }

    load_configs();
    setComboBoxActive(user_data, 0);
}

createSignalObjectFunc(click_action_createconfig, GtkComboBox) {
    char path[1000] = {0};

    const char *host = entryBufferGetText(host_entry_buffer);
    const char *port = entryBufferGetText(port_entry_buffer);
    const char *username = entryBufferGetText(username_entry_buffer);
    const char *password = entryBufferGetText(password_entry_buffer);

    sprintf(path, "%s/sshto%s.sh", CONFIG_DIRECTORY_PATH, host);

    char buffer[10000] = {0};
    sprintf(buffer, SSHTO_TEMPLATE, host, port, username, password);
    // if (!FileExists(path)) {
    //     if (FileCreateEmpty(path)) {

    //     }
    // }
    // 已存在：true，或创建成功：true
    if (FileCreateEmpty(path)) {
        FileWirteWithBuffer(path, buffer, strlen(buffer));
        textBufferSetText(config_text_buffer, buffer, strlen(buffer));

        char perm_str[100];
        permissionToStringWithPath(path, perm_str);
        printf("文件权限: %s\n",  perm_str);

        if (!isExecutePermission(path)) {
            setExecutePermission(path);

            S_CLEARN(perm_str);
            if (permissionToStringWithPath(path, perm_str)) {
                printf("设置文件执行权限: %s\n", perm_str);
            }
        }
    }
    load_configs();
    setComboBoxActive(user_data, 0);
}


static void activate(GtkApplication *app, gpointer user_data) {
    GtkWindow *window;

    window = createWindowWithTitleSize(app, "gtk-sshto-expect", 600, 300);

    config_list_store = createTreeStore(2, G_TYPE_STRING, G_TYPE_STRING);
    
    GtkComboBox *config_comb = createComboBoxWithModel(load_configs());
    setCellLayout(config_comb, createCellRendererText(), "text", 0, NULL, false);
    setComboBoxActive(config_comb, 0);

    host_entry_buffer = createEntryBuffer(NULL);
    port_entry_buffer = createEntryBufferWithText("22");
    username_entry_buffer = createEntryBuffer(NULL);
    password_entry_buffer = createEntryBuffer(NULL);

    config_text_buffer = createTextBuffer(NULL);

    GtkEntry *host_entry = createEntryWithEntryBuffer(host_entry_buffer);
    GtkEntry *port_entry = createEntryWithEntryBuffer(port_entry_buffer);
    GtkEntry *username_entry = createEntryWithEntryBuffer(username_entry_buffer);
    GtkEntry *password_entry = createEntryWithEntryBuffer(password_entry_buffer);

    gpointer text_view = createWidgetVerticalExpand(createTextViewWithTextBuffer(config_text_buffer), true);
    setWidgetMargin(text_view, 10, 10, 0, 5);

    GtkBox *mainBox = createBoxWithVerticalAppends(5, 
        createBoxWithHorizntalMarginAlignAppends(5, 0, ACENTER, 
            config_comb,
            createButtonAction(config_comb, "读取配置", clicked_action_comb_readconfig),
            createButtonAction(config_comb, "删除配置", clicked_action_comb_deleteconfig),
            NULL
        ),
        createBoxWithHorizntalMarginAlignAppends(5, 0, ACENTER, 
            createLabel("服务器地址:"),
            host_entry,
            createLabel("服务器端口:"),
            port_entry,
            NULL
        ),
        createBoxWithHorizntalMarginAlignAppends(5, 0, ACENTER, 
            createLabel("用户名:"),
            username_entry,
            createLabel("密码:"),
            password_entry,
            NULL
        ),
        createBoxWithHorizntalMarginAlignAppends(5, 0, ACENTER, 
            createButtonAction(NULL, "预览配置文件", click_action_previewconfig),
            createButtonAction(config_comb, "写入配置文件", click_action_createconfig),
            NULL
        ),
        createSeparatorWithHorizntal(),
        text_view,
        NULL
    );

    // objectBindProperty(s, sp, t, tp, flags);
    // g_object_bind_property(combo, "active-id", entry, "text",  G_BINDING_BIDIRECTIONAL);
    // objectBindProperty(config_comb, "active-id", config_comb, "text", G_BINDING_BIDIRECTIONAL);

    connectTargetAction(config_comb, config_comb, "changed", clicked_action_comb_readconfig);
    clicked_action_comb_readconfig(NULL, config_comb);

    setWindowChild(window, mainBox);
    showWindow(window);
}

int	main(int argc, char **argv) {

    GtkApplication *app;
    int status;

    app = createApplicationConnectActivate("gtk.example.template", 
                                G_APPLICATION_FLAGS_NONE, activate);
    status = runApplication(app, argc, argv);
    objectUnref(app);

    return status;
}

